package com.quanyue.music.system.service.impl;

import com.quanyue.auto.fs.StoreService;
import com.quanyue.auto.util.AssertUtils;
import com.quanyue.auto.util.StringUtils;
import com.quanyue.music.domain.constant.*;
import com.quanyue.music.domain.entity.ExcelAutoError;
import com.quanyue.music.domain.entity.FmVip;
import com.quanyue.music.domain.entity.PlayList;
import com.quanyue.music.system.dto.PlayListExcel;
import com.quanyue.music.system.dto.PlayListExcelResult;
import com.quanyue.music.system.mapper.AutoExcelMapper;
import com.quanyue.music.system.mapper.PlayListMapper;
import com.quanyue.music.system.service.AutoExcelService;
import com.quanyue.music.system.service.PlayListService;
import com.quanyue.music.system.type.*;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class PlayListServiceImpl implements PlayListService {
    private final String path = "/opt/music/admin/server/static/dist/excel/waiting/";
    @Autowired
    private PlayListMapper playListMapper;
    @Autowired
    private StoreService storeService;
    @Autowired
    private AutoExcelService autoExcelService;
    @Autowired
    private AutoExcelMapper autoExcelMapper;
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public void clearPlay(String date, FMChannel channel) {
        LocalDateTime startTime = LocalDateTime.parse(date + "T00:00:00");
        LocalDateTime endTime = LocalDateTime.parse(date + "T23:59:59");
        playListMapper.clearPlay(startTime, endTime, channel);
    }

    @Override
    public LocalDateTime findVipEndTime(String userId) {
        LocalDateTime dateTime = null;
        FmVip vip = playListMapper.findVipByUserId(userId);
        if (vip != null) {
            dateTime = vip.getEndTime();
        }
        return dateTime;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List <ExcelAutoError> addExcel(MultipartFile file, FMChannel channel, String data) {
        List <ExcelAutoError> result = Collections.EMPTY_LIST;
        try {
            LocalDateTime initTime = LocalDateTime.parse(data + "T00:00:00");
            String filename = file.getOriginalFilename();
            File f = new File(path + filename);
            FileUtils.copyInputStreamToFile(file.getInputStream(), f);
            PlayListExcelResult listExcels = autoExcelService.readExcel(f, filename);
            // 获取Excel数据
            List <PlayListExcel> excels = listExcels.getPlayListExcels();
            List <PlayList> playLists = new ArrayList <>();
            for (int i = 0; i < excels.size(); i++) {
                Boolean check = false;
                PlayList list = new PlayList();
                PlayList checkPlay = playListMapper.findByTimeAndNum(initTime, channel);
                if (checkPlay != null)
                    throw new AssertUtils.ValidateException("不允许重复添加,在Excel表中行" + i + 1 + "留白即可");
                List <String> musicIds = playListMapper.findByFmKeyId(excels.get(i).getSegmentKey());
                List <String> billIds = playListMapper.findByFmKeyId(excels.get(i).getInsertKey());
                if (musicIds.isEmpty()) {
                    ExcelAutoError autoError = new ExcelAutoError();
                    autoError.setSessionId(listExcels.getSessionId());
                    autoError.setCreateTime(LocalDateTime.now());
                    autoError.setKeyId(excels.get(i).getSegmentKey() == null ? " " : excels.get(i).getSegmentKey());
                    autoError.setErrorType(AutoExcelError.ERROR_SEGMENT_NULL);
                    autoError.setRowNumber(i + 1);
                    autoError.setColumNumber(1);
                    autoExcelMapper.insert(autoError);
                    check = true;
                }
                if (billIds.isEmpty()) {
                    ExcelAutoError autoError = new ExcelAutoError();
                    autoError.setSessionId(listExcels.getSessionId());
                    autoError.setCreateTime(LocalDateTime.now());
                    autoError.setKeyId(excels.get(i).getInsertKey() == null ? " " : excels.get(i).getInsertKey());
                    autoError.setErrorType(AutoExcelError.ERROR_INSERT_NULL);
                    autoError.setRowNumber(i + 1);
                    autoError.setColumNumber(2);
                    autoExcelMapper.insert(autoError);
                    check = true;
                }
                if (check) continue;
                String musicId = musicIds.get(0);
                String billId = billIds.get(0);
                list.setStatus(FMPlayStatus.SUBMIT);
                list.setFmAdvertise(billId);
                list.setFmMusic(musicId);
                list.setCreateTime(LocalDateTime.now());
                list.setModifyTime(LocalDateTime.now());
                list.setDelFlag(false);
                list.setChannelNum(channel);
                list.setStartTime(initTime.plusMinutes(i * 30));
                list.setEndTime(list.getStartTime().plusMinutes(30));
                playLists.add(list);
            }
            playListMapper.insertAll(playLists);
            result = findError(listExcels.getSessionId());
        } catch (IOException io) {
            log.error("IO异常：", io);
        }
        return result;
    }

    @Override
    public List <ExcelAutoError> findError(String sessionId) {
        return autoExcelMapper.findBySessionId(sessionId);
    }

    @Override
    public void add(PlayList playList) {
        PlayList check = playListMapper.findByTimeAndNum(playList.getStartTime(), playList.getChannelNum());
        if (check != null) throw new AssertUtils.ValidateException("不允许重复添加!");
        playList.setStatus(FMPlayStatus.SUBMIT);
        playList.setCreateTime(LocalDateTime.now());
        playList.setModifyTime(LocalDateTime.now());
        playList.setDelFlag(false);
        playListMapper.insert(playList);
    }

    @Override
    public void update(PlayList playList) {
        PlayList check = playListMapper.findOne(playList.getId());
        AssertUtils.notNull(check, "没有该播放列表");
        playList.setStatus(FMPlayStatus.SUBMIT);
        playList.setCreateTime(check.getCreateTime());
        playList.setModifyTime(LocalDateTime.now());
        playList.setDelFlag(false);
        playListMapper.update(playList);
    }

    @Override
    public void delete(String id) {
        PlayList playList = new PlayList();
        playList.setDelFlag(true);
        playList.setModifyTime(LocalDateTime.now());
        throw new AssertUtils.ValidateException("1.0版本只能更改");
//        playListMapper.update(playList);
    }

    @Override
    public Boolean check(String date, FMChannel fmChannel) {
        LocalDate localDate = LocalDate.parse(date);
        Integer checkCount = playListMapper.findCountByDate(localDate, fmChannel);
        if (checkCount != 48) return false;
        return true;
    }

    @Override
    public List <FMPlayList> findPlayList(String date, FMChannel fmChannel) {
        LocalDate localDate = LocalDate.parse(date);
        List <FMPlayList> fmPlayLists = playListMapper.findMusicByDate(localDate, fmChannel);
        fmPlayLists.forEach(fmPlayList -> {
            BillInfo billInfo = playListMapper.findBillByDate(fmPlayList.getId());
            if (billInfo != null) {
                fmPlayList.setBillTitle(billInfo.getTitle());
                fmPlayList.setBillKeyId(billInfo.getKeyId());
            }
        });
        if (fmPlayLists.isEmpty()) return Collections.EMPTY_LIST;
        return fmPlayLists;
    }

    @Override
    public List <FMPlayDetail> findPlay(FMPlayRequest request, String userId) {
        List <FMPlayDetail> details = new ArrayList <>();
        TimeZoneType zoneType = request.getZoneType();
        log.info("请求的时区+请求的用户ID: {}", request.getZoneType() + ":" + userId);
        LocalDateTime zoneTime = LocalDateTime.now();
        switch (zoneType) {
            case PST:
                zoneTime = LocalDateTime.now().minusHours(3);
                break;
            case CST:
                zoneTime = LocalDateTime.now().minusHours(1);
                break;
            case MST:
                zoneTime = LocalDateTime.now().minusHours(2);
                break;
            default:
                break;
        }
        FMPlayDetail detail = playListMapper.findPlayByDate(zoneTime, request.getFmChannel(), userId);
        if (detail == null || detail.getFmMusic() == null || detail.getFmAdvertise() == null) {
            detail = playListMapper.findSos();
            if (detail == null) return Collections.EMPTY_LIST;
            if (zoneTime.getMinute() >= 30) {
                detail.setStartTime(zoneTime.minusMinutes(zoneTime.getMinute() - 30));
            } else {
                detail.setStartTime(zoneTime.minusMinutes(zoneTime.getMinute() - 0));
            }
        }
        detail.setNames(playListMapper.findFmNames(detail.getMusicId()));
        List <FMPlayImages> playImagesList = playListMapper.selectByTime(zoneTime);
        for (FMPlayImages playImages : playImagesList) {
            switch (playImages.getFmChannel()) {
                case CHANNEL_ONE:
                    detail.setChannelOneImage(playImages.getImage());
                    break;
                case CHANNEL_TWO:
                    detail.setChannelTwoImage(playImages.getImage());
                    break;
                default:
                    break;
            }
        }
        String image = null;
        if (playListMapper.findSos() != null)
            image = playListMapper.findSos().getImage();
        if (StringUtils.isBlank(detail.getChannelOneImage()))
            detail.setChannelOneImage(image);
        if (StringUtils.isBlank(detail.getChannelTwoImage()))
            detail.setChannelTwoImage(image);
        long leadTime = Duration.between(detail.getStartTime(), zoneTime).getSeconds();
        detail.setLike(true);
        if (StringUtils.isBlank(detail.getLikeId())) detail.setLike(false);
        detail.setLeadTime(leadTime);
        String join1 = detail.getFmFile().substring(0, detail.getFmFile().lastIndexOf("/") + 1);
        String join2 = detail.getFmFile().substring(detail.getFmFile().lastIndexOf("/") + 1, detail.getFmFile().lastIndexOf("."));
        int baseSecond = 540;
        if (detail.getTypeName().equals(FMType.SOS))
            baseSecond = 600;
        detail.setTotalTime(baseSecond * 3);
        if (leadTime >= baseSecond * 2 && leadTime < baseSecond * 3) {
            detail.setFmFile(join1 + "split2-" + join2 + ".mp3");
            detail.setTotalTime(baseSecond);
        } else if (leadTime >= baseSecond && leadTime < baseSecond * 3) {
            detail.setFmFile(join1 + "split1-" + join2 + ".mp3");
            detail.setTotalTime(baseSecond * 2);
        }
        detail.setVip(false);
        FmVip vip = playListMapper.findVipByUserId(userId);
        if (vip != null) {
            detail.setVip(true);
            detail.setEndTime(vip.getEndTime());
        }
        log.info("是否是VIP: {}", detail.getVip() + "VIP详情:" + vip);
        if (!detail.getTypeName().equals(FMType.SOS)) {
            FMPlayDetail billDetail = playListMapper.findPlayById(detail.getId());
            billDetail.setLeadTime(leadTime - 1620);
            billDetail.setNames(playListMapper.findFmNames(billDetail.getMusicId()));
            playListMapper.selectByTimeBill(zoneTime).forEach(billImages -> {
                switch (billImages.getFmChannel()) {
                    case CHANNEL_ONE:
                        billDetail.setChannelOneImage(billImages.getImage());
                        break;
                    case CHANNEL_TWO:
                        billDetail.setChannelTwoImage(billImages.getImage());
                        break;
                    default:
                        break;
                }
            });
            if (StringUtils.isBlank(billDetail.getChannelOneImage()))
                billDetail.setChannelOneImage(image);
            if (StringUtils.isBlank(billDetail.getChannelTwoImage()))
                billDetail.setChannelTwoImage(image);
            details.add(billDetail);
            details.add(detail);
        } else {
            details.add(detail);
        }

        details.forEach(fmPlayDetail -> {
            fmPlayDetail.setChannelOneImage(storeService.toPublic(fmPlayDetail.getChannelOneImage()));
            fmPlayDetail.setChannelTwoImage(storeService.toPublic(fmPlayDetail.getChannelTwoImage()));
        });

        return details;
    }


}
